home *** CD-ROM | disk | FTP | other *** search
/ Sprite 1984 - 1993 / Sprite 1984 - 1993.iso / src / machserver / 1.098 / raid / devDebug.c < prev    next >
C/C++ Source or Header  |  1991-06-27  |  11KB  |  420 lines

  1. /* 
  2.  * devDebug.c --
  3.  *
  4.  *    This module implements the BlockDevice interface for a device
  5.  *    which echos requests to stdout.
  6.  *
  7.  * Copyright 1989 Regents of the University of California
  8.  * All rights reserved.
  9.  * Permission to use, copy, modify, and distribute this
  10.  * software and its documentation for any purpose and without
  11.  * fee is hereby granted, provided that the above copyright
  12.  * notice appear in all copies.  The University of California
  13.  * makes no representations about the suitability of this
  14.  * software for any purpose.  It is provided "as is" without
  15.  * express or implied warranty.
  16.  */
  17.  
  18. #include "sync.h"
  19. #include <sprite.h>
  20. #include <stdio.h>
  21. #include <stdlib.h>
  22. #include "fs.h"
  23. #include "devRaid.h"
  24. #include "devBlockDevice.h"
  25. #include "schedule.h"
  26. #include "timer.h"
  27. #include "devRaidProto.h"
  28.  
  29. typedef struct DebugHandle {
  30.     DevBlockDeviceHandle blockHandle;    /* Must be FIRST field. */
  31.     Fs_Device        *devPtr;    /* Device corresponding to handle */
  32. } DebugHandle;
  33.  
  34. #ifdef TESTING
  35. /*
  36.  * Storage for contents of simulated disks.
  37.  * (16 disks of 32 bytes each)
  38.  */
  39. static char devDebugData[4][4][32] = {
  40. "A0A1A2A3A4A5A6A7a0a1a2a3a4a5a6a7",
  41. "B0B1B2B3B4B5B6B7b0b1b2b3b4b5b6b7",
  42. "C0C1C2C3C4C5C6C7c0c1c2c3c4c5c6c7",
  43. "D0D1D2D3D4D5D6D7d0d1d2d3d4d5d6d7",
  44. "E0E1E2E3E4E5E6E7e0e1e2e3e4e5e6e7",
  45. "F0F1F2F3F4F5F6F7f0f1f2f3f4f5f6f7",
  46. "G0G1G2G3G4G5G6G7g0g1g2g3g4g5g6g7",
  47. "H0H1H2H3H4H5H6H7h0h1h2h3h4h5h6h7",
  48. "I0I1I2I3I4I5I6I7i0i1i2i3i4i5i6i7",
  49. "J0J1J2J3J4J5J6J7j0j1j2j3j4j5j6j7",
  50. "K0K1K2K3K4K5K6K7k0k1k2k3k4k5k6k7",
  51. "L0L1L2L3L4L5L6L7l0l1l2l3l4l5l6l7",
  52. "M0M1M2M3M4M5M6M7m0m1m2m3m4m5m6m7",
  53. "N0N1N2N3N4N5N6N7n0n1n2n3n4n5n6n7",
  54. "O0O1O2O3O4O5O6O7o0o1o2o3o4o5o6o7",
  55. "P0P1P2P3P4P5P6P7p0p1p2p3p4p5p6p7",
  56. };
  57.  
  58. static char logData[30000];
  59. #endif
  60.  
  61. /*
  62.  * Forward Declarations.
  63.  */
  64. static ReturnStatus BlockIOProc();
  65. static ReturnStatus BlockIOProc1();
  66. static ReturnStatus ReleaseProc();
  67. static ReturnStatus IOControlProc();
  68.  
  69.  
  70. /*
  71.  *----------------------------------------------------------------------
  72.  *
  73.  * DevDebugAttach --
  74.  *
  75.  *    Attach a Debug logical device to the system.
  76.  *
  77.  * Results:
  78.  *    The DevBlockDeviceHandle of the device.
  79.  *
  80.  * Side effects:
  81.  *    Modifies Debug data structure.
  82.  *
  83.  *----------------------------------------------------------------------
  84.  */
  85.  
  86. DevBlockDeviceHandle *
  87. DevDebugAttach(devicePtr)
  88.     Fs_Device    *devicePtr;    /* The device to attach. */
  89. {
  90.     DebugHandle    *handlePtr;
  91.  
  92.     handlePtr = (DebugHandle *) malloc(sizeof(DebugHandle));
  93.     if (devicePtr->unit < 200) {
  94.         handlePtr->blockHandle.blockIOProc = BlockIOProc;
  95.     } else {
  96.         handlePtr->blockHandle.blockIOProc = BlockIOProc1;
  97.     }
  98.     handlePtr->blockHandle.releaseProc = ReleaseProc;
  99.     handlePtr->blockHandle.IOControlProc = IOControlProc;
  100.     if (devicePtr->unit == 99) {
  101.     handlePtr->blockHandle.minTransferUnit = 64;
  102.     } else {
  103.     handlePtr->blockHandle.minTransferUnit = 1;
  104.     }
  105.     handlePtr->blockHandle.maxTransferSize = 1<<30;
  106.     handlePtr->devPtr = devicePtr;
  107.     return (DevBlockDeviceHandle *) handlePtr;
  108. }
  109.  
  110.  
  111. /*
  112.  *----------------------------------------------------------------------
  113.  *
  114.  * ReleaseProc --
  115.  *
  116.  *    Block device release proc.
  117.  *
  118.  * Results:
  119.  *    Return status.
  120.  *
  121.  * Side effects:
  122.  *
  123.  *----------------------------------------------------------------------
  124.  */
  125. /*ARGUSED*/
  126. static ReturnStatus
  127. ReleaseProc(handlePtr)
  128.     DebugHandle    *handlePtr; /* Handle pointer of device. */
  129. {
  130.     free((char *) handlePtr);
  131.     return SUCCESS;
  132. }
  133.  
  134.  
  135. /*
  136.  *----------------------------------------------------------------------
  137.  *
  138.  * IOControlProc --
  139.  *
  140.  *      Do a special operation on a raw SCSI Disk.
  141.  *
  142.  * Results:
  143.  *      None.
  144.  *
  145.  * Side effects:
  146.  *      Depends on operation.
  147.  *
  148.  *----------------------------------------------------------------------
  149.  */
  150.  
  151. /*ARGSUSED*/
  152. static ReturnStatus
  153. IOControlProc(blockDevHandlePtr, ioctlPtr, replyPtr) 
  154.     DevBlockDeviceHandle
  155.         *blockDevHandlePtr;  /* Handle of the device to operate on. */
  156.     Fs_IOCParam *ioctlPtr;    /* Standard I/O Control parameter block */
  157.     Fs_IOReply *replyPtr;    /* outBuffer length and returned signal */
  158. {
  159.     return SUCCESS;
  160. }
  161.  
  162.  
  163. /*
  164.  *----------------------------------------------------------------------
  165.  *
  166.  * BlockIOProc --
  167.  *
  168.  *    Perform block IO on specified Debug device.
  169.  *    Note that this procedure directly calles the callback procedure
  170.  *    before returning.
  171.  *
  172.  * Results:
  173.  *    The return code from the I/O operation.
  174.  *
  175.  * Side effects:
  176.  *    Modifies devDebugData (i.e. the simulated disk contents) if
  177.  *    TESTING is defined and the operation is a write.
  178.  *
  179.  *----------------------------------------------------------------------
  180.  */
  181.  
  182. static ReturnStatus
  183. BlockIOProc(handlePtr, requestPtr) 
  184.     DevBlockDeviceHandle  *handlePtr; /* Handle pointer of device. */
  185.     DevBlockDeviceRequest *requestPtr; /* IO Request to be performed. */
  186. {
  187.     DebugHandle       *debugHandlePtr = (DebugHandle *) handlePtr;
  188.  
  189.     /*
  190.      * Debug device with unit number == 101 is the same as /dev/null except
  191.      * that you can also read infinite amounts of garbage from it as well
  192.      * as writing to it.
  193.      */
  194.     if (debugHandlePtr->devPtr->unit < 100) {
  195.     printf("\nBlockIOProc\n");
  196.     PrintTime();
  197.     PrintHandle(handlePtr);
  198.     PrintDevice(debugHandlePtr->devPtr);
  199.     PrintRequest(requestPtr);
  200.     }
  201.  
  202. #ifdef TESTING
  203. {
  204.     DevBlockDeviceRequest *localRequestPtr = requestPtr; 
  205.     ReturnStatus    status;
  206.     int            row, col;
  207.     char      **statusCtrl;
  208.     int            i;
  209.  
  210.     if (debugHandlePtr->devPtr->unit == 99) {
  211.     int *iBuf;
  212.     if (requestPtr->operation == FS_READ) {
  213.         bcopy(logData+requestPtr->startAddress,
  214.             requestPtr->buffer,requestPtr->bufferLen);
  215.     } else {
  216.         bcopy(requestPtr->buffer,
  217.             logData+requestPtr->startAddress,
  218.             requestPtr->bufferLen);
  219.     }
  220.     printf("XFER: ");
  221.     iBuf = (int *) requestPtr->buffer;
  222.     for (i = 0; i < requestPtr->bufferLen/4; i++) {
  223.         printf("%d ", iBuf[i]);
  224.     }
  225.     printf("\n");
  226.     requestPtr->doneProc(requestPtr, SUCCESS, requestPtr->bufferLen);
  227.     return SUCCESS;
  228.     }
  229.  
  230.     row = debugHandlePtr->devPtr->unit/10;
  231.     col = debugHandlePtr->devPtr->unit%10;
  232.  
  233.     if (requestPtr->operation == FS_READ) {
  234.     bcopy(devDebugData[row][col]+requestPtr->startAddress,
  235.         requestPtr->buffer,requestPtr->bufferLen);
  236.     } else {
  237.     bcopy(requestPtr->buffer,
  238.         devDebugData[row][col]+requestPtr->startAddress,
  239.         requestPtr->bufferLen);
  240.     }
  241.  
  242.     printf("XFER: ");
  243.     printf("\"");
  244.     for (i = 0; i < requestPtr->bufferLen; i++) {
  245.         printf("%c", (char)
  246.         (requestPtr->buffer[i] == '\0' ? '_' : requestPtr->buffer[i]));
  247.  
  248.     }
  249.     printf("\"");
  250.     printf("\n");
  251.  
  252.     statusCtrl = (char **) requestPtr->ctrlData[0];
  253.     if (statusCtrl == (char **) NIL) {
  254.     status = SUCCESS;
  255.     } else {
  256.         status = (*(*statusCtrl)++ == 's' ? SUCCESS: FAILURE);
  257.     }
  258.     (void) printf("status: %d\n", status);
  259.  
  260.     if (Spawn("disk") == 0) {
  261.     Delay(10.0);
  262.         localRequestPtr->doneProc(localRequestPtr,
  263.         status, localRequestPtr->bufferLen);
  264.     Terminate();
  265.     } else {
  266.         return SUCCESS;
  267.     }
  268. }
  269. #else
  270.     requestPtr->doneProc(requestPtr, SUCCESS, requestPtr->bufferLen);
  271.     return SUCCESS;
  272. #endif TESTING
  273. }
  274.  
  275.  
  276. /*
  277.  *----------------------------------------------------------------------
  278.  *
  279.  * timerCallBackProc --
  280.  *
  281.  *    Callback procedure for BlockIOProc1.
  282.  *    This callback procedure called from timer interrupts which
  283.  *    simulate IO interrupts that an IO to a real device would result in.
  284.  *
  285.  * Results:
  286.  *    The return code from the I/O operation.
  287.  *
  288.  * Side effects:
  289.  *    None.
  290.  *
  291.  *----------------------------------------------------------------------
  292.  */
  293.  
  294. #ifndef TESTING
  295. typedef struct TimerCallBackData {
  296.     Timer_QueueElement      *timerQueueElemPtr;
  297.     void         (*proc)();
  298.     DevBlockDeviceRequest *requestPtr;
  299.     ReturnStatus       status;
  300.     int               amountTransferred;    
  301. } TimerCallBackData;
  302.  
  303. static void
  304. timerCallBackProc(time, timerCallBackDataPtr)
  305.     Timer_Ticks        time;
  306.     TimerCallBackData  *timerCallBackDataPtr;
  307. {
  308.     timerCallBackDataPtr->proc(timerCallBackDataPtr->requestPtr,
  309.         timerCallBackDataPtr->status, timerCallBackDataPtr->amountTransferred);
  310.     free((char*) timerCallBackDataPtr->timerQueueElemPtr);
  311.     free((char*) timerCallBackDataPtr);
  312. }
  313. #endif TESTING
  314.  
  315.  
  316. /*
  317.  *----------------------------------------------------------------------
  318.  *
  319.  * BlockIOProc1 --
  320.  *
  321.  *    Perform block IO on specified Debug device.
  322.  *    This procedure is similar to BlockIOProc except that the callback
  323.  *    is done at interrupt level via timer interrupts.
  324.  *
  325.  * Results:
  326.  *    The return code from the I/O operation.
  327.  *
  328.  * Side effects:
  329.  *    None.
  330.  *
  331.  *----------------------------------------------------------------------
  332.  */
  333.  
  334. static ReturnStatus
  335. BlockIOProc1(handlePtr, requestPtr) 
  336.     DevBlockDeviceHandle  *handlePtr;  /* Handle pointer of device. */
  337.     DevBlockDeviceRequest *requestPtr; /* IO Request to be performed. */
  338. {
  339. #ifdef TESTING
  340.     DevBlockDeviceRequest *localRequestPtr = requestPtr; 
  341.     DebugHandle       *debugHandlePtr = (DebugHandle *) handlePtr;
  342.     ReturnStatus    status;
  343.     char      **statusCtrl;
  344.     int            row, col;
  345.     int            i;
  346.  
  347.     printf("\nBlockIOProc\n");
  348.     PrintTime();
  349.     PrintHandle(handlePtr);
  350.     PrintDevice(debugHandlePtr->devPtr);
  351.     PrintRequest(requestPtr);
  352.  
  353.     row = debugHandlePtr->devPtr->unit/10;
  354.     col = debugHandlePtr->devPtr->unit%10;
  355.  
  356.     if (requestPtr->operation == FS_READ) {
  357.     bcopy(devDebugData[col][row],requestPtr->buffer,requestPtr->bufferLen);
  358.     } else {
  359.     bcopy(requestPtr->buffer,devDebugData[col][row],requestPtr->bufferLen);
  360.     }
  361.     printf("XFER: ");
  362.     for (i = 0; i < requestPtr->bufferLen; i++) {
  363.         printf("%c", (char) requestPtr->buffer[i]);
  364.     }
  365.     printf("\n");
  366.  
  367.     /*
  368.      * When using the Debug device, ctrlData should be initialized with
  369.      * status control information.
  370.      */
  371.     statusCtrl = (char **) requestPtr->ctrlData[0];
  372.     status = (*(*statusCtrl)++ == 's' ? SUCCESS: FAILURE);
  373.     (void) printf("status: %d\n", status);
  374.  
  375.     /*
  376.      * Simulate request queueing.
  377.      */
  378.     if (Spawn("disk")) {
  379.     return SUCCESS;
  380.     } else {
  381.         /*
  382.          * Child simulates IO Device.
  383.          */
  384.         Delay(100.0);
  385.     localRequestPtr->buffer[0] =
  386.         debugHandlePtr->devPtr->unit/10+'0';
  387.     localRequestPtr->buffer[1] =
  388.         debugHandlePtr->devPtr->unit%10+'0';
  389.     localRequestPtr->doneProc(localRequestPtr,
  390.                   status, localRequestPtr->bufferLen);
  391.     Terminate();
  392.  
  393.         /*
  394.          * This never gets executed and is only here to shutup lint.
  395.          */
  396.         return SUCCESS;
  397.     }
  398. #else
  399. {
  400.     Timer_QueueElement *timerQueueElemPtr;
  401.     TimerCallBackData  *timerCallBackDataPtr;
  402.  
  403.     timerQueueElemPtr = (Timer_QueueElement *)
  404.             malloc(sizeof(Timer_QueueElement));
  405.     timerCallBackDataPtr = (TimerCallBackData *)
  406.             malloc(sizeof(TimerCallBackData));
  407.     timerQueueElemPtr->routine = timerCallBackProc;
  408.     timerQueueElemPtr->clientData = (ClientData) timerCallBackDataPtr;
  409.     timerQueueElemPtr->interval = 10;
  410.     timerCallBackDataPtr->timerQueueElemPtr = timerQueueElemPtr;
  411.     timerCallBackDataPtr->proc = requestPtr->doneProc;
  412.     timerCallBackDataPtr->requestPtr = requestPtr;
  413.     timerCallBackDataPtr->status = SUCCESS;
  414.     timerCallBackDataPtr->amountTransferred = requestPtr->bufferLen;
  415.     Timer_ScheduleRoutine(timerQueueElemPtr, TRUE);
  416.     return SUCCESS;
  417. }
  418. #endif TESTING
  419. }
  420.